package mornd.test3;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;

import java.net.URL;

/**
 * @author: mornd
 * @dateTime: 2023/5/4 - 22:30
 */
public class App {
    public static void main(String[] args) throws Exception {
        GenericApplicationContext context = new GenericApplicationContext();
        context.registerBean("config", Config.class);

        //context.registerBean(ComponentScanPostProcessor.class); // 自定义 ComponentScan 后置处理器
        context.registerBean(AtBeanPostProcessor.class);  // 自定义 Bean 后置处理器
        context.registerBean(MapperPostProcessor.class); // 自定义 mybatis的 MapperScan 后置处理器

        // 识别 @Configuration @ComponentScan @Bean @Import @importResource 注解
//        context.registerBean(ConfigurationClassPostProcessor.class);
//        //  mybatis 扫描 mapper 接口
//        context.registerBean(MapperScannerConfigurer.class, bd -> {
//            bd.getPropertyValues().add("basePackage", "mornd.test3.mapper");
//        });

        context.refresh();

        String[] names = context.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

        context.close();
    }

    private static void custom(GenericApplicationContext context) throws Exception {
        ComponentScan componentScan =
                AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);

        // 生成 @component 注解所在的类的 bean 的名称
        AnnotationBeanNameGenerator nameGenerator = new AnnotationBeanNameGenerator();
        if(componentScan != null) {
            String[] packages = componentScan.basePackages();
            for (String p : packages) {
                String path = "classpath*:" + p.replace(".", "/") + "/**/*.class";

                Resource[] resources = context.getResources(path);
                CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();
                for (Resource r : resources) {
                    //System.out.println(r);

                    MetadataReader mr = readerFactory.getMetadataReader(r);
                    // 类名
                    String className = mr.getClassMetadata().getClassName();

                    // 注解信息
                    AnnotationMetadata annoMetadata = mr.getAnnotationMetadata();

                    boolean b = annoMetadata.hasAnnotation(Component.class.getName());
                    System.out.println("类"+ className + "是否包含@Component：" + b);

                    boolean b1 = annoMetadata.hasMetaAnnotation(Component.class.getName());
                    System.out.println("类"+ className + "是否包含@Component或其派生注解：" + b1); // 例如：@Controller

                    if(b || b1) {
                        AbstractBeanDefinition beanDefinition =
                                BeanDefinitionBuilder.genericBeanDefinition(className).getBeanDefinition();

                        // 生成名称 mornd.test3.Config ==> config
                        String name = nameGenerator.generateBeanName(beanDefinition, context);
                        // 添加 bean 定义到容器中
                        context.getDefaultListableBeanFactory().registerBeanDefinition(name, beanDefinition);
                    }
                }
            }
        }

    }
}
